package cn.jofei.netty.server;

import cn.jofei.common.ano.Component;
import cn.jofei.common.ano.Value;
import cn.jofei.common.netty.protocol.ProtocolFrameDecoder;
import cn.jofei.netty.hadler.ClientMessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * 通信端口 服务
 *
 * @author Jofei Bao
 * @version ngbao v2.0
 * @date 2022年10月18日 11:29
 */
@Slf4j
@Component
public class SocketClientServer extends SocketServer {

    @Value(name = "${server.port}")
    private Integer port = 4443;
    /**
     * 客户端消息处理器
     */
    private static final ClientMessageHandler MESSAGE_HANDLER = new ClientMessageHandler();

    @Override
    public void start() {
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(BOSS_GROUP, WORK_GROUP)
                .channel(NioServerSocketChannel.class)
                // 给 ServerSocketChannel 的配置 连接队列数配置 accept 处理的队列
                .option(ChannelOption.SO_BACKLOG, 256)
                // 给 SocketChannel 的配置
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel sc) throws Exception {
                        sc.pipeline()
                                .addLast(new ProtocolFrameDecoder())
                                .addLast(LOGGING_HANDLER)
                                //心跳监测
                                .addLast(new IdleStateHandler(5, 0, 0))
                                .addLast(MESSAGE_CODEC)
                                .addLast(MESSAGE_HANDLER)
                        ;
                    }
                });
        bootstrap.bind(port).addListener(e -> {
            if (e.isSuccess()) {
                log.info("客户端通信端口：{}，创建成功", port);
            } else {
                log.error("通信端口服务启动异常", e.cause());
            }
        });
    }
}
